package com.hlkj.pay.service.order.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.pojo.LocalContext;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.order.IPayOrderAppService;
import com.hlkj.pay.common.CommonResultCode;
import com.hlkj.pay.common.MerchantResultCode;
import com.hlkj.pay.common.OpenApiResultCode;
import com.hlkj.pay.common.PayResultCode;
import com.hlkj.pay.dto.LocalMerchantRequest;
import com.hlkj.pay.dto.merchant.CashierConfigDto;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.model.common.CommonAppDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantInfoDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.service.common.ICommonAppConfigService;
import com.hlkj.pay.service.merchant.IMerchantApplicationService;
import com.hlkj.pay.service.merchant.IMerchantService;
import com.hlkj.pay.service.order.ICashierService;
import com.hlkj.pay.service.order.IPayOrderService;
import com.hlkj.pay.service.pay.IPayWayService;
import com.hlkj.pay.service.pay.IProviderService;
import com.hlkj.pay.util.AESUtils;
import com.hlkj.pay.util.AlipayOAuthUtils;
import com.hlkj.pay.util.OrderCodeUtil;
import com.hlkj.pay.util.WeChatOAuthUtils;
import com.hlkj.pay.vo.openapi.order.resp.PayOrderSubmitApiResp;
import com.hlkj.pay.vo.order.req.CashierPayParamReq;
import com.hlkj.pay.vo.order.req.PayOrderParamReq;
import com.hlkj.pay.vo.order.req.PreOrderPayReq;
import com.hlkj.pay.vo.order.resp.CashierMchInfoResp;
import com.hlkj.pay.vo.order.resp.PayOrderResp;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Service
@Slf4j
@RequiredArgsConstructor
public class CashierServiceImpl implements ICashierService {

    private final IMerchantApplicationService merchantApplicationService;

    private final IMerchantService merchantService;

    private final IPayWayService payWayService;

    private final IPayOrderAppService payOrderAppService;

    private final OrderCodeUtil orderCodeUtil;

    private final IProviderService providerService;

    private final IPayOrderService payOrderService;

    private final ICommonAppConfigService commonAppConfigService;

    @Value("${hlkj.domain}")
    private String domain;

    @Override
    public CommonResult<PayOrderSubmitApiResp> createOrder(CashierPayParamReq cashierPayParamReq) {
        try {
            String encryptedAppId = cashierPayParamReq.getAppToken();
            String appId = AESUtils.decrypt(encryptedAppId);
            MerchantAppDO merchantAppDO = merchantApplicationService.queryDetailByAppId(appId);
            if (merchantAppDO == null) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_NOT_EXIST);
            }
            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantAppDO.getStatus())) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_NOT_EFFECT);
            }
            String sn = merchantAppDO.getSn();
            MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(sn);
            if (merchantInfoDO == null) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_NOT_EXIST);
            }
            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantInfoDO.getStatus())) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_NOT_EFFECT);
            }
            // 获取支付方式
            PayEnums.PAY_TYPE payType = PayEnums.PAY_TYPE.fromByType(cashierPayParamReq.getPayType());
            if (payType == null) {
                log.info("提交的支付类型错误:{}", cashierPayParamReq.getPayType());
                return CommonResult.error(OpenApiResultCode.PAY_WAY_NOT_EXITS);
            }
            PayEnums.SCENE_PAY_TYPE scenePayType = PayEnums.SCENE_PAY_TYPE.fromByType(cashierPayParamReq.getPaySubType());
            if (scenePayType == null) {
                log.info("提交的支付方式错误:{}", cashierPayParamReq.getPaySubType());
                return CommonResult.error(OpenApiResultCode.PAY_WAY_NOT_EXITS);
            }
            //支付场景默认1 线下
            if (cashierPayParamReq.getSceneType() == null) cashierPayParamReq.setSceneType(1);
            // 获取支付方式
            PayWayDO payWayDO = payWayService.queryByType(payType.getCode(), scenePayType, cashierPayParamReq.getSceneType());
            if (payWayDO == null) {
                return CommonResult.error(OpenApiResultCode.PAY_WAY_NOT_EXITS);
            }
            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(payWayDO.getStatus())) {
                return CommonResult.error(OpenApiResultCode.PAY_WAY_NOT_EFFECT);
            }
            PayOrderParamReq payOrderParamReq = new PayOrderParamReq();
            // CommonEnum.COMMON_APP_TYPE commonAppType = CommonEnum.COMMON_APP_TYPE.from(scenePayType, payType);
            // if(commonAppType!=null){
            //     MerchantAppQueryDto merchantAppQueryDto=new MerchantAppQueryDto();
            //     merchantAppQueryDto.setAppId(appId);
            //     merchantAppQueryDto.setCommonAppType(commonAppType);
            //     merchantAppQueryDto.setStatus(CommonEnum.YES_NO_TYPE.YES.getCode());
            //     List<MerchantAppChannelDO> merchantAppChannelList = merchantApplicationService.queryEffectProvideAppId(merchantAppQueryDto);
            //     if(CollectionUtils.isEmpty(merchantAppChannelList)){
            //         return CommonResult.error(OpenApiResultCode.MERCHANT_APP_CHANNEL_NOT_EXIST);
            //     }
            //     MerchantAppChannelDO merchantAppChannelDO = MerchantAppChannelRouterUtil.router(merchantAppChannelList);
            //     payOrderParamReq.setMchChannelCode(merchantAppChannelDO.getChannelCode());
            // }
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            payOrderParamReq.setPayWayCode(payWayDO.getCode());
            payOrderParamReq.setSceneType(payWayDO.getSceneType());
            payOrderParamReq.setPaySubType(payWayDO.getSubType());
            payOrderParamReq.setPayType(PayEnums.PAY_TYPE.fromByCode(payWayDO.getType()).getType());
//            payOrderParamReq.setMchOrderNo(orderCodeUtil.orderNo(PayOrderEnums.ORDER_NO_TYPE.CASHIER));
            payOrderParamReq.setMchOrderNo(cashierPayParamReq.getMchOrderNo());
            payOrderParamReq.setAmount(cashierPayParamReq.getAmount());
            if (org.springframework.util.StringUtils.hasText(cashierPayParamReq.getRemark())) {
                payOrderParamReq.setSubject(cashierPayParamReq.getRemark());
                payOrderParamReq.setDescription(cashierPayParamReq.getRemark());
            }
            else {
                // MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(merchantQr.getSn());
                // if (org.springframework.util.StringUtils.hasText(merchantInfoDO.getName())) {
                //     payOrderParamReq.setSubject(merchantInfoDO.getName());
                //     payOrderParamReq.setDescription(merchantInfoDO.getName());
                // }
                // else {
                    payOrderParamReq.setSubject("收银台收款");
                    payOrderParamReq.setDescription("收银台收款");
                // }
            }
            payOrderParamReq.setClientIp(ServletUtil.getClientIP(request, null));
            String servletPath = request.getServletPath();
            if (StringUtils.isBlank(servletPath)) {
                servletPath = request.getPathInfo();
            }
            LocalMerchantRequest localMerchantRequest = new LocalMerchantRequest();
            localMerchantRequest.setStartTime(System.currentTimeMillis());
            localMerchantRequest.setRequestUrl(servletPath);
            localMerchantRequest.setSn(sn);
            localMerchantRequest.setMerchantAppDO(merchantAppDO);
            localMerchantRequest.setMerchantInfoDO(merchantInfoDO);
            localMerchantRequest.setRequestMethod(request.getMethod());
            LocalContext.set(localMerchantRequest);
            payOrderParamReq.setOrderType(PayOrderEnums.PAY_ORDER_TYPE.CRASH);
            return payOrderAppService.submitOrder(payOrderParamReq);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("收银台下单异常 订单信息:{},message:{}", JsonUtils.toJsonString(cashierPayParamReq), e.getMessage(),e);
            return CommonResult.error(CommonResultCode.PARAMETER_MISSING.getCode(), e.getMessage());
        }
    }

    @Override
    public CommonResult<PayOrderResp> submitOrder(String orderNo, String authCode) {
        if (StringUtils.isBlank(orderNo) || StringUtils.isEmpty(authCode)) {
            return CommonResult.error(CommonResultCode.PARAMETER_MISSING);
        }

        PayOrderDO payOrderDO = payOrderService.queryPayOrder(orderNo);
        if (payOrderDO == null) {
            return CommonResult.error(MerchantResultCode.MERCHANT_PAY_ORDER_NOT_EXIST);
        }
        PreOrderPayReq preOrderPayReq = BeanUtil.copyProperties(payOrderDO, PreOrderPayReq.class);
        preOrderPayReq.setAuthCode(authCode);
        return payOrderAppService.preSubmitOrder(preOrderPayReq);
    }

    @Override
    public CommonResult<CashierMchInfoResp> getInfo(String appToken) {
        try {
            String appId = AESUtils.decrypt(appToken);
            if (appId.isEmpty()) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_NOT_EFFECT);
            }
            MerchantAppDO merchantAppDO = merchantApplicationService.queryDetailByAppId(appId);
            if (merchantAppDO == null) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_NOT_EXIST);
            }
            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantAppDO.getStatus())) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_APP_NOT_EFFECT);
            }
            String sn = merchantAppDO.getSn();
            MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(sn);
            if (merchantInfoDO == null) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_NOT_EXIST);
            }
            if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantInfoDO.getStatus())) {
                return CommonResult.error(OpenApiResultCode.MERCHANT_NOT_EFFECT);
            }
            CashierMchInfoResp cashierMchInfoResp = new CashierMchInfoResp();
            cashierMchInfoResp.setMchOrderNo(orderCodeUtil.orderNo(PayOrderEnums.ORDER_NO_TYPE.CASHIER));
            cashierMchInfoResp.setMchName(merchantInfoDO.getShortName());
            CashierConfigDto cashierConfigDto = merchantAppDO.getCashierConfigDto();
            if (cashierConfigDto != null) {
                if (!StringUtils.isBlank(cashierConfigDto.getName())) {
                    cashierMchInfoResp.setMchName(cashierConfigDto.getName());
                }
                cashierMchInfoResp.setPcPayTypeList(cashierConfigDto.getPc());
                cashierMchInfoResp.setMobilePayTypeList(cashierConfigDto.getMobile());
            }
            return CommonResult.success(cashierMchInfoResp);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取商户信息异常，app_token:{},message:{}", appToken, e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<String> wechatAuth(String orderNo, String redirectUrl) {
        try {
            if (StringUtils.isBlank(orderNo) || StringUtils.isBlank(redirectUrl)) {
                return CommonResult.error(CommonResultCode.PARAMETER_MISSING);
            }

            PayOrderDO payOrderDO = payOrderService.queryPayOrder(orderNo);
            if (payOrderDO == null) {
                return CommonResult.error(MerchantResultCode.MERCHANT_PAY_ORDER_NOT_EXIST);
            }
            ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(payOrderDO.getProviderCode(), payOrderDO.getChannelCode());
            if (providerChannelConfigDO == null) {
                return CommonResult.error(PayResultCode.PROVIDER_CHANNEL_NOT_EXITS);
            }
            CommonAppDO commonAppDO = commonAppConfigService.detail(providerChannelConfigDO.getWechatDefaultPubId());
            if (commonAppDO == null) {
                return CommonResult.error(CommonResultCode.COMMON_APP_NOT_EXIST);
            }
            String url = WeChatOAuthUtils.getAuthCode(commonAppDO.getAppId(), redirectUrl);

            return CommonResult.success(url);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取微信授权链接异常，orderNo:{},message:{}", orderNo, e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<String> alipayAuth(String orderNo, String redirectUrl) {
        try {
            if (StringUtils.isBlank(orderNo) || StringUtils.isBlank(redirectUrl)) {
                return CommonResult.error(CommonResultCode.PARAMETER_MISSING);
            }

            PayOrderDO payOrderDO = payOrderService.queryPayOrder(orderNo);
            if (payOrderDO == null) {
                return CommonResult.error(MerchantResultCode.MERCHANT_PAY_ORDER_NOT_EXIST);
            }
            ProviderChannelConfigDO providerChannelConfigDO = providerService.queryConfig(payOrderDO.getProviderCode(), payOrderDO.getChannelCode());
            if (providerChannelConfigDO == null) {
                return CommonResult.error(PayResultCode.PROVIDER_CHANNEL_NOT_EXITS);
            }

            CommonAppDO commonAppDO = commonAppConfigService.detail(providerChannelConfigDO.getAlipayPubId());
            if (commonAppDO == null) {
                return CommonResult.error(CommonResultCode.COMMON_APP_NOT_EXIST);
            }
            String url = AlipayOAuthUtils.getAuthCode(commonAppDO.getAppId(), redirectUrl);

            return CommonResult.success(url);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取支付宝授权链接异常，orderNo:{},message:{}", orderNo, e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }
}
